<?php

namespace MUD;

class Client extends \Sock\SocketClientBroadcast{
    public $user_id;
    public $authenticated;
    public $username;
    public $sex;
    public $last_online;
    public $score;
    public $prefs = array();
    public $inventory=array();
    
    public function __construct($socket, &$server){
        parent::__construct($socket, $server);
        
        $this->last_online = 'Never';
        $this->score=0;
        $this->sex='Male';
        $this->username='Guest'.mt_rand(100, 999);
        $this->authenticated=false;
        
        $this->prefs=array(
            'show_room_descriptions' => 1
        );
    }
    
    public function login(){
        do{
            R::current()->client->send("Plase enter our username:", "\t", false);
            $username = R::current()->client->read_smart();
        }while(empty($username));
        do{
            R::current()->client->send("Now enter your password:", "\t", false);
            $password = R::current()->client->read_smart();
        }while(empty($password));
        $password_debug = $password;
        $password = R::current()->encrypt($password);
        
        $login = R::current()->dbo->select("*", "users", "username='".$username."' AND password='".$password."'", 1);
        
        if(R::current()->dbo->rows == 1){
            $user = R::current()->dbo->result[0];
            $this->user_id = $user['id'];
            $this->authenticated = true;
            $this->username = $user['username'];
            $this->sex = $user['sex'];
            $this->last_online = $user['last_online'];
            $this->score = $user['score'];
            
            //update last_online to now in db
            $data=array(
                'last_online'=> date('Y-m-d H:i:s', time()),
                'pid' => getmypid()
            );
            R::current()->dbo->update('users', $data, "id='".$this->user_id."'", 1);
            
            //move player in db
            $data=array(
                'client_id' => $this->user_id,
                'pid' => getmypid(),
                'location' => 1
            );
            R::current()->dbo->query("INSERT INTO clientracker(`client_id`,`pid`,`location`) VALUES('".$this->user_id."','".getmypid()."','1')", false);
            
            return true;
        }else{
            \Sock\SocketServer::cLog("Failed login attempt for user ".$username." (".$password_debug.")");
            R::current()->client->send("Invalid username or password provided. Please try again.\n\n", "\n", false);
        }
    }
    
    public function register(){
        $username='';
        $password='';
        $username='';
        $gender='';
        $email='';
        $newsletter='n';
        
        function setUsername(){
            do{
                R::current()->send("First, please choose a name for your character:", "\t", false);
                $username = R::current()->read();
                
                if(strlen($username) < 5 || strlen($username) > 45 || !preg_match('/[a-zA-Z0-9]/', $username)){
                    R::current()->send("Please ensure your username is between 5 and 45 characters in length and only contains letters and numbers.", "\n", false);
                    $username='';
                }
            }while(empty($username));
            return $username;
        }
        function setPassword(){
            do{
                R::current()->send("Now enter a password for your account:", "\t", false);
                $password = R::current()->read();
                if(strlen($password) < 6 || strlen($password) > 75){
                    R::current()->send("Please choose a password that is between 6 and 75 characters in length.", "\n", false);
                    $password='';
                }else{
                    R::current()->send("Please confirm that password:", "\t", false);
                    $confirm = R::current()->read();
                    
                    if($password != $confirm){
                        R::current()->send("Oops! Those passwords did not match.", "\n", false);
                        $password='';
                        $current='';
                    }
                }
            }while(empty($password));
            return $password;
        }
        function setEmail(){
            do{
                R::current()->send("Please enter your Email Address:", "\t", false);
                $email = R::current()->read();
                
                if(preg_match('[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', $email)){
                    //invalid email
                    R::current()->send("Invalid email address provided. Please enter a valid email address.", "\n", false);
                    $email='';
                }
            }while(empty($email));
            return $email;
        }
        function setGender(){
            do{
                R::current()->send("Would you like your character to be Male or Female?(m/f):", "\t", false);
                $gender=R::current()->read();
                $gender=strtolower($gender);
                if($gender == 'm' || $gender == 'f'){
                    break;
                }else{
                    R::current()->send("You can only be a male or female. Sorry!", "\n", false);
                    $gender='';
                }
            }while(empty($gender));
            return $gender;
        }
        
        $username=setUsername();
        $password=setPassword();
        $email=setEmail();
        $gender=setGender();
        
        do{
            $out = "\n\nYour Details:\n";
            $out.= "1) Username: ".$username."\n";
            $out.= "2) Password: ".$password."\n";
            $out.= "3) Email: ".$email."\n";
            $out.= "4) Gender: ".($gender == 'f' ? 'Female' : 'Male');
            R::current()->send($out . "\n\nPlease confirm the above is correct.\n".
                    "If you wish to change anything, enter the corresponding number and press ENTER\notherwize, type c and press ENTER.");
            $option = strtolower(R::current()->read());
            switch($option){
                case '1' : $username=setUsername(); break;
                case '2' : $password = setPassword(); break;
                case '3' : $email = setEmail(); break;
                case '4' : $gender = setGender(); break;
                default : R::current()->send("", "\n", false);
            }
        }while($option != 'c');
        
        $password = R::current()->encrypt($password);
        
        $data=array(
            'username' => $username,
            'password' => $password,
            'email' => $email,
            'sex' => $gender,
            'registered' => date('Y-m-d H:i:s', time())
        );
        
        $mkuser = R::current()->dbo->insert("users", $data);
        
        if($mkuser){
            R::current()->client->send("Account created. Logging you in...", "\n", false);
            $last_id = R::current()->dbo->select('id', "users", "username='".$username."' AND password='".$password."'",'1');
            $this->autoLogin($last_id[0]['id']);
        }else{
            R::current()->client->send("Oops! it looks like something went wrong creating your account.\nPlease try again later.", "\n\n", false);
            R::current()->client->disconnected();
        }
    }
    
    private function autoLogin($id){
        $getUser = R::current()->dbo->select("*", "users", "id='".$id."'", 1);
        $user = R::current()->dbo->result[0];
        $this->user_id=$id;
        $this->authenticated=true;
        $this->username = $user['username'];
        $this->sex = $user['sex'];
        $this->score = $user['score'];
        $this->last_online = $user['last_online'] == '0000-00-00 00:00:00' ? date('Y-m-d H:i', time()) : date('Y-m-d H:i', strtotime($user['last_online']));
        
        //update lastonline to now
        R::current()->dbo->update("users", array("last_online" => date('Y-m-d H:i:s', time())), "id='".$id."'", 1);
        
        $data = array(
            'client_id' => $this->user_id,
            'pid' => getmypid(),
            'location' => 1
        );
        R::current()->dbo->insert('clientracker', $data);
        return true;
    }
    
    public function read_smart(){
        $input = trim(parent::read());
        $input = str_replace("\n", '', $input);
        return $input;
    }
    
    public function send($message, $nl="\n", $pointer=true){
        if($pointer){
            $message .= "\n" . PHPREG::$client_cursor;
        }else{
            $message .= $nl;
        }
        parent::send($message);
    }
    
    public function whisper($message, $target_user, $pid_sent=false, $not_service=true){
        if(!$pid_sent){
            $getPid = R::current()->dbo->select("pid", "users", "username='".$target_user."'", 1);
            if(R::current()->dbo->rows == 1){
                $destination_pid = R::current()->dbo->result[0]['pid'];
                if($destination_pid == 0){
                return false;
                }
            }
        }else{
            $destination_pid = $target_user;
        }
        
        $message = ((!$not_service) ? '' : $this->username." tells you ") . trim($message);
        
        parent::sendPrivateMessage($message, $destination_pid);
        return true;
    }
    
    public function takeItem($name){
        $item = R::current()->items->getItemByName($name);
        if(is_object($item)){
            if($item->location == R::current()->map->room->id && $item->location_type == 'map'){
                //take item
                R::current()->updateItemLocation($item->id, 'player');
                $this->inventory[] = $item;
            }else{
                $this->send("Its not here!");
            }
        }else{
            $this->send("I don't know what your after.");
        }
    }
}